#include "ipc.h"
/*
 * get_ipc_id() 从/proc/sysvipc/文件系统中获取IPC的id号
 * pfile: 对应/proc/sysvipc/目录中的IPC文件分别为
 * msg-消息队列,sem-信号量,shm-共享内存
 * key:对应要获取的IPC的id号的键值
 */
int get_ipc_id(char *proc_file,key_t key)
{
	FILE *pf;
	int i,j;
	char line[BUFSZ],colum[BUFSZ];
	if((pf = fopen(proc_file,"r")) == NULL){
		perror("Proc file not open");
		exit(EXIT_FAILURE);
	}
	fgets(line, BUFSZ,pf);
	while(!feof(pf)){
		i = j = 0;
		fgets(line, BUFSZ,pf);
		while(line[i] == ' ') i++;
		while(line[i] !=' ') colum[j++] = line[i++];
		colum[j] = '\0';
		if(atoi(colum) != key) continue;
		j=0;
		while(line[i] == ' ') i++;
		while(line[i] !=' ') colum[j++] = line[i++];
		colum[j] = '\0';
		i = atoi(colum);
		close(pf);
		return i;
	}	
	close(pf);
	return -1;
}
/*
 * 信号灯上的down/up操作
 * semid:信号灯数组标识符
 * semnum:信号灯数组下标
 * buf:操作信号灯的结构
 */
int down(int sem_id)
{
	struct sembuf buf;
	buf.sem_op = -1;
	buf.sem_num = 0;
	buf.sem_flg = SEM_UNDO;
	if((semop(sem_id,&buf,1)) <0) {
		perror("down error ");
		exit(EXIT_FAILURE);
	}
	return EXIT_SUCCESS;
}
int up(int sem_id)
{
	struct sembuf buf;
	buf.sem_op = 1;
	buf.sem_num = 0;
	buf.sem_flg = SEM_UNDO;
	if((semop(sem_id,&buf,1)) <0) {
		perror("up error ");
		exit(EXIT_FAILURE);
	}
	return EXIT_SUCCESS;
	}
int set_sem(key_t sem_key,int sem_val,int sem_flg)
{
	int sem_id;
Sem_uns sem_arg;
	//信号量是否建立
	if((sem_id = get_ipc_id("/proc/sysvipc/sem",sem_key)) < 0 )
	{
		//semget建立一个信号灯,其标号返回到sem_id
		if((sem_id = semget(sem_key,1,sem_flg)) < 0)
		{
			perror("semaphore create error");
			exit(EXIT_FAILURE);
		}
		sem_arg.val = sem_val; //设置信号量的初值
		if(semctl(sem_id,0,SETVAL,sem_arg) <0)
		{
			perror("semaphore set error");
			exit(EXIT_FAILURE);
		}
		}
		return sem_id;
}
char * set_shm(key_t shm_key,int shm_num,int shm_flg)
{
	int shm_id;
	char * shm_buf;
	if((shm_id = get_ipc_id("/proc/sysvipc/shm",shm_key)) < 0 )
	{
	//shmget建立一个长度为shm_num字节的共享内存,其标号返回到shm_id
		if((shm_id = shmget(shm_key,shm_num,shm_flg)) <0)
		{
			perror("shareMemory set error");
			exit(EXIT_FAILURE);
		}
		if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0)
		{
			perror("get shareMemory error");
			exit(EXIT_FAILURE);
		}
		*shm_buf = 0;
	}
	if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0)
	{
		perror("get shareMemory error");
		exit(EXIT_FAILURE);
	}
	return shm_buf;
}
int set_msq(key_t msq_key,int msq_flg)
{
	int msg_id;
	//测消息队列是否建立
	if((msg_id = get_ipc_id("/proc/sysvipc/msg",msq_key)) < 0 )
	{
		//msgget建立一个消息队列,其标号返回到msg_id
		if((msg_id = msgget(msq_key,msq_flg)) < 0)
		{
			perror("messageQueue set error");
			exit(EXIT_FAILURE);
		}
	}
	return msg_id;
}
